package com.joezhou.spring.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author JoeZhou
 */
@Slf4j
@Aspect
@Component
public class UserAspectByAnn {

    /**
     * 标记@Pointcut的方法视为切点方法，方法名随意但方法体必须为空
     * PE表达式用来指定我将要AOP哪些方法
     * PE表达式格式：返回值 包.类.方法(形参)
     */
    @Pointcut("execution(* com.joezhou.spring.aspect.UserServiceImpl.selectById(..))")
    public void pc01() {
    }

    /**
     * `@Around` 表示这是一个环绕通知方法
     *
     * @param pjp 表示连接点，负责获取参数，放行代码等工作
     * @return 方法的返回值，必须为Object类型
     */
    @Around("pc01()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) {
        int[] result = null;
        try {
            log.info("前置通知：登录鉴权...");

            // pjp.getArgs()：获取业务方法的形参
            // pjp.proceed()：调用业务方法
            result = (int[]) pjp.proceed(pjp.getArgs());
        } catch (Throwable e) {
            log.error("异常通知：爆发异常..." + e);
        } finally {
            log.info("后置通知：记录日志...");

            // 改变返回值
            if (result != null) {
                log.info("返回后通知：将原返回值 " + Arrays.toString(result) + " 改为 [4, 5, 6]...");
                result[0] = 4;
                result[1] = 5;
                result[2] = 6;
            }
        }
        return result;
    }

}